package cn.tqfeiyang.springplus.generator;

import cn.tqfeiyang.springplus.generator.config.GeneratorConfig;
import cn.tqfeiyang.springplus.generator.config.TableFill;
import cn.tqfeiyang.springplus.generator.engine.TemplateEngine;
import cn.tqfeiyang.springplus.generator.engine.VelocityTemplateEngine;
import cn.tqfeiyang.springplus.generator.jdbc.DatabaseQuery;
import cn.tqfeiyang.springplus.generator.jdbc.TableInfo;
import cn.tqfeiyang.springplus.generator.name.NameFormat;
import cn.tqfeiyang.springplus.generator.util.ObjectUtils;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;

import java.util.Map;
import java.util.Scanner;
import java.util.function.BiConsumer;

/**
 * 代码自动生成器
 */
public class AutoGenerator extends GeneratorConfig {

    private final DatabaseQuery databaseQuery;

    private final TemplateEngine templateEngine;

    public AutoGenerator() {
        this.databaseQuery = new DatabaseQuery(this);
        this.templateEngine = new VelocityTemplateEngine(this);
    }

    public void batchOutput(BiConsumer<TemplateEngine, TableInfo> consumer) {
        databaseQuery.queryTables().forEach(tableInfo -> {
            consumer.accept(templateEngine, tableInfo);
        });

        openOutputDir();
    }

    public static void main(String[] args) {
        AutoGenerator generator = new AutoGenerator();
        generator.setJdbcUrl("jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true");
        generator.setJdbcUsername("root");
        generator.setJdbcPassword("123456");
        generator.addTablePrefix("t_", "c_", "base_", "system_", "sys_", "oa_");
        generator.setOutputDir("D:\\DOWNLOADS\\CodeGenerator");
        //generator.setOutputDir("Z:\\spring-plus-apiserver");
        generator.setAutoOpen(false);
        generator.setRootPackage("cn.tqfeiyang.smartadmin");
        generator.addTableFills(new TableFill("version", FieldFill.INSERT));
        generator.addTableFills(new TableFill("deleted", FieldFill.INSERT));
        generator.addTableFills(new TableFill("create_id", FieldFill.INSERT));
        generator.addTableFills(new TableFill("create_time", FieldFill.INSERT));
        generator.addTableFills(new TableFill("update_id", FieldFill.INSERT_UPDATE));
        generator.addTableFills(new TableFill("update_time", FieldFill.INSERT_UPDATE));

//        outputSingleTable(generator, "base_company", "warehouse", "基础");
//        outputSingleTable(generator, "base_warehouse", "warehouse", "基础");
//        outputSingleTable(generator, "base_supplier", "warehouse", "基础");
//        outputSingleTable(generator, "base_customer", "warehouse", "基础");

        //outputSingleTable(generator, "system_user", "system", "系统");
        //outputSingleTable(generator, "system_role", "system", "系统");

//        outputSingleTable(generator, "sys_permission", "system", "系统");
//        outputSingleTable(generator, "sys_menu", "system", "系统");
        //outputSingleTable(generator, "sys_user", "system", "系统");
//        outputSingleTable(generator, "sys_role", "system", "系统");
//        outputSingleTable(generator, "sys_config", "system", "系统");
//        outputSingleTable(generator, "sys_operation_log", "system", "系统");
//        outputSingleTable(generator, "sys_login_log", "system", "系统");

        //outputSingleTable(generator, "oa_notice", "office", "办公");
        //outputSingleTable(generator, "oa_notice_category", "office", "办公");

//        outputSingleTable(generator, "oa_position", "business.organization", "组织");
//        outputSingleTable(generator, "oa_department", "business.organization", "组织");
//        outputSingleTable(generator, "oa_employee", "business.organization", "组织");

        outputSingleTable(generator, "oa_position", null, null);
        outputSingleTable(generator, "oa_address", null, null);
        outputSingleTable(generator, "oa_department", null, null);
        outputSingleTable(generator, "oa_employee", null, null);
        //outputSingleTable(generator, "oa_employee_role", null, null);

    }

    private static void outputSingleTable(AutoGenerator generator,
                                          String tableName,
                                          String moduleName,
                                          String apifoxFolder) {
        generator.getIncludeTables().clear();
        generator.addIncludeTable(tableName);
        generator.setModuleName(moduleName);
        generator.setApifoxFolder(apifoxFolder);
        generator.batchOutput((engine, table) -> {
            Map<String, Object> objectMap = table.getNf();

            //engine.writeToFile("smartadmin/constant.java", table, NameFormat.ConstantJavaFile, true);
            //engine.writeToFile("smartadmin/entity.java", table, NameFormat.EntityJavaFile, true);

            engine.writeToFile("smartadmin/constant.java", table, ObjectUtils.get(objectMap, "constantClass.filePath"), true);
            engine.writeToFile("smartadmin/entity.java", table, ObjectUtils.get(objectMap, "entityClass.filePath"), true);

            if (table.isSupportMapper()) {
                 if (table.getTableType().equalsIgnoreCase("CROSS")) {
                    engine.writeToFile("smartadmin/mapper_cross.java", table, NameFormat.MapperJavaFile, true);
                    engine.writeToFile("smartadmin/mapper_cross.xml", table, NameFormat.MapperXmlFile, true);
                } else {
                    engine.writeToFile("smartadmin/mapper_entity.java", table, NameFormat.MapperJavaFile, true);
                    engine.writeToFile("smartadmin/mapper_entity.xml", table, NameFormat.MapperXmlFile, true);
                }
            }

            if (table.isSupportService()) {
                engine.writeToFile("smartadmin/validator.java", table, ObjectUtils.get(objectMap, "validatorClass.filePath"), true);
                engine.writeToFile("smartadmin/service_curd.java", table, ObjectUtils.get(objectMap, "curdServiceClass.filePath"), true);
                engine.writeToFile("smartadmin/service_excel.java", table, ObjectUtils.get(objectMap, "excelServiceClass.filePath"), true);
                if (table.getHasManyToManyJoins()) {
                    engine.writeToFile("smartadmin/service_assign.java", table, ObjectUtils.get(objectMap, "assignServiceClass.filePath"), true);
                }
                if (table.isSupportCache()) {
                    engine.writeToFile("smartadmin/service_cache.java", table, ObjectUtils.get(objectMap, "cacheServiceClass.filePath"), true);
                }
                // 产生List服务，根据数据表是否支持缓存，使用不同的模版
                if (table.isSupportCache()) {
                    engine.writeToFile("smartadmin/service_list_cache.java", table, ObjectUtils.get(objectMap, "listServiceClass.filePath"), true);
                } else {
                    engine.writeToFile("smartadmin/service_list_mapper.java", table, ObjectUtils.get(objectMap, "listServiceClass.filePath"), true);
                }
                // 产生Tree服务
                if (table.isSupportTree()) {
                    engine.writeToFile("smartadmin/service_tree.java", table, ObjectUtils.get(objectMap, "treeServiceClass.filePath"), true);
                    engine.writeToFile("smartadmin/response_tree.java", table, ObjectUtils.get(objectMap, "treeResponseClass.filePath"), true);
                }
            }

            if (table.isSupportController()) {
                engine.writeToFile("smartadmin/controller_curd.java", table, ObjectUtils.get(objectMap, "curdControllerClass.filePath"), true);
                engine.writeToFile("smartadmin/controller_excel.java", table, ObjectUtils.get(objectMap, "excelControllerClass.filePath"), true);
                //engine.writeToFile("smartadmin/controller_tests.java", table, NameFormat.ControllerTestsJavaFile, true);
                if (table.getHasManyToManyJoins()) {
                    engine.writeToFile("smartadmin/controller_assign.java", table, ObjectUtils.get(objectMap, "assignControllerClass.filePath"), true);
                }
                if (table.isSupportCache()) {
                    engine.writeToFile("smartadmin/controller_cache.java", table, ObjectUtils.get(objectMap, "cacheControllerClass.filePath"), true);
                }
                if (table.isSupportTree()) {
                    engine.writeToFile("smartadmin/controller_tree.java", table, ObjectUtils.get(objectMap, "treeControllerClass.filePath"), true);
                }
            }

            if (table.isSupportService() || table.isSupportController()) {
                engine.writeToFile("smartadmin/request_query.java", table, NameFormat.RequestQueryJavaFile, true);
                engine.writeToFile("smartadmin/request_create.java", table, NameFormat.RequestCreateJavaFile, true);
                engine.writeToFile("smartadmin/request_update.java", table, NameFormat.RequestUpdateJavaFile, true);
                engine.writeToFile("smartadmin/response_query.java", table, NameFormat.ResponseQueryJavaFile, true);
                engine.writeToFile("smartadmin/response_detail.java", table, NameFormat.ResponseDetailJavaFile, true);
            }

            engine.writeToFile("smartadmin/mysql.sql", table, NameFormat.MysqlSQLFile, true);
            engine.writeToFile("smartadmin/vue_api.js", table, NameFormat.VueApiFile, true);
            engine.writeToFile("smartadmin/vue_list.vue", table, NameFormat.VueListFile, true);
            engine.writeToFile("smartadmin/vue_drawer.vue", table, NameFormat.VueDrawerFile, true);
        });
    }

    private static String inputTableName(String defaultTable) {
        Scanner scanner = new Scanner(System.in);
        System.out.print(String.format("请输入一个表名 (%s) : ", defaultTable));
        String tableName = scanner.nextLine();
        return StringUtils.isNotBlank(tableName) ? tableName : defaultTable;
    }

}